module Laya.GameInstance {

    export class Game {

        private background: Manager.Background;

        public bulletLayer: Laya.Sprite;
        public enemyLayer:  Laya.Sprite;
        public dropLayer:   Laya.Sprite;
        public playerLayer: Laya.Sprite;
        
        private gameInfo: Manager.GameInfo;

        private gameManager: Manager.GameManager;
        private dataManager: Manager.DataManager;

        constructor() {
            Laya.init(Manager.Background.imageWidth, Manager.Background.imageHeight, Laya.WebGL);
            // Laya.init(Manager.Background.imageWidth, Manager.Background.imageHeight);
            Laya.stage.scaleMode = "exactfit";

            Laya.loader.load([
                {"url": "res/background.png", "type": Laya.Loader.IMAGE},
                {"url": "res/ui.json", "type": Laya.Loader.ATLAS},
                {"url": "res/drop.json", "type": Laya.Loader.ATLAS},
                {"url": "res/bullet.json", "type": Laya.Loader.ATLAS},
                {"url": "res/player.json", "type": Laya.Loader.ATLAS},
                {"url": "res/enemy.json", "type": Laya.Loader.ATLAS},
                {"url": "res/config.json", "type": Laya.Loader.JSON},
                {"url": "res/packet.api.json", "type": Laya.Loader.JSON},
            ], Laya.Handler.create(this, this.onResLoaded), null);

            Laya.Stat.show(0, 80);
        }

        private onResLoaded() {

            this.background = new Manager.Background();
            Laya.stage.addChild(this.background);
            
            this.bulletLayer = new Laya.Sprite();
            Laya.stage.addChild(this.bulletLayer);

            this.enemyLayer = new Laya.Sprite();
            Laya.stage.addChild(this.enemyLayer);
            
            this.playerLayer = new Laya.Sprite();
            Laya.stage.addChild(this.playerLayer);

            this.dropLayer = new Laya.Sprite();
            Laya.stage.addChild(this.dropLayer);

            this.gameInfo = new Manager.GameInfo();
            Laya.stage.addChild(this.gameInfo);

            this.gameManager = Manager.GameManager.getInstance();
            this.dataManager = Manager.DataManager.getInstance();

            this.startOrRestart();
        }

        public startOrRestart() {

            this.dataManager.startOrRestart();
            this.gameManager.startOrRestart();
            this.background.startOrRestart();
            this.gameInfo.startOrRestart();

            this.resume();

            this.gameManager.createEnemy(3);
        }

        public onLoop(): void {

            this.dataManager.onLoop();
            this.gameManager.onLoop();
            this.background.onLoop();
            this.gameInfo.onLoop();

            this.gameManager.enemys.forEach(enemy => { if (enemy && enemy.isAlive()) {

                let distance = Math.sqrt(Math.pow(this.gameManager.player.x - enemy.x, 2) + Math.pow(this.gameManager.player.y - enemy.y, 2));
                if (distance <= enemy.radius + this.gameManager.player.radius - 2) {
                    // Player Collides With Enemy
                    enemy.looseBlood(1);
                    this.gameManager.player.looseBlood(1);
                }

                this.gameManager.bullets.forEach(bullet => { if (bullet && bullet.isAlive()) {
                    let distance = Math.sqrt(Math.pow((bullet.x - enemy.x), 2) + Math.pow((bullet.y - enemy.y), 2));
                    if (distance <= bullet.radius + enemy.radius - 2) {
                        // Enemy Collides With Bullet
                        bullet.looseBlood(1);
                        enemy.looseBlood(1);
                    }
                }});
            }});
            
            this.gameManager.drops.forEach(drop => { if (drop && drop.isAlive()) {
                let distance = Math.sqrt(Math.pow(this.gameManager.player.x - drop.x, 2) + Math.pow(this.gameManager.player.y - drop.y, 2));
                if (distance <= drop.radius + this.gameManager.player.radius - 2) {
                    // Player Collides With Drop
                    drop.pickedUpBy(this.gameManager.player);
                    drop.looseBlood(1);
                }
            }});
        }

        private onMouseMove(e: Laya.Event) {
            let bounds: Laya.Rectangle = this.gameManager.player.getBounds();
            this.gameManager.player.pos(Laya.stage.mouseX - bounds.width/2, Laya.stage.mouseY - bounds.height / 2);
        }

        public pause() {
            if (Manager.DataManager.getInstance().blood > 0) {

                this.dataManager.pause();
                this.gameManager.pause();
                this.background.pause();
                this.gameInfo.pause();

                Laya.timer.clear(this, this.onLoop);
                Laya.stage.off("mousemove", this, this.onMouseMove);
                
            }
        }

        public resume() {

            if (Manager.DataManager.getInstance().blood > 0) {

                this.dataManager.resume();
                this.gameManager.resume();
                this.background.resume();
                this.gameInfo.resume();

                Laya.timer.loop(20, this, this.onLoop);
                Laya.stage.on("mousemove", this, this.onMouseMove);
                
            }
        }

        public stop() {

            this.dataManager.stop();
            this.gameManager.stop();
            this.background.stop();
            this.gameInfo.stop();

            Laya.timer.clear(this, this.onLoop);
            Laya.stage.off("mousemove", this, this.onMouseMove);
        }

    }

}

let gameInstance: Laya.GameInstance.Game = new Laya.GameInstance.Game();